
//Copyright 1997-2009 Syrinx Development, Inc.
//This file is part of the Syrinx Web Application Framework (SWAF).
// == BEGIN LICENSE ==
//
// Licensed under the terms of any of the following licenses at your
// choice:
//
//  - GNU General Public License Version 3 or later (the "GPL")
//    http://www.gnu.org/licenses/gpl.html
//
//  - GNU Lesser General Public License Version 3 or later (the "LGPL")
//    http://www.gnu.org/licenses/lgpl.html
//
//  - Mozilla Public License Version 1.1 or later (the "MPL")
//    http://www.mozilla.org/MPL/MPL-1.1.html
//
// == END LICENSE ==
using System;
using System.Configuration;
using System.Xml;

namespace Swaf.Xml
{
	/// <summary>
	/// Summary description for LineInfoXmlDocument.
	/// </summary>
	public class LineInfoXmlDocument : XmlDocument
	{
		public override XmlElement CreateElement(string prefix, string localname, string nsURI)
		{
			LineInfoXmlElement elem = new LineInfoXmlElement(prefix, localname, nsURI, this);
			return elem;
		}

		public override void Load(string filename)
		{
			XmlTextReader reader = null;
            try
            {
                reader = new XmlTextReader(filename);
                reader.MoveToContent();
                this.AppendChild(loadElement(reader));
            }
            catch (Exception e)
            {
                string msg = "";
                if (reader != null)
                    msg = string.Format("Error processing configuration file {0} on Line {1}.", filename, reader.LineNumber);
                else
                    msg = string.Format("Error processing configuration file {0}", filename);
                System.Diagnostics.Debug.WriteLine(msg + " Exception: " + e.ToString());
                throw new BaseException(msg, e);
            }
            finally
            {
                reader.Close();
            }
		}

		protected LineInfoXmlElement loadElement(XmlTextReader reader)
		{
			LineInfoXmlElement el = new LineInfoXmlElement(reader.Prefix, reader.Name, reader.NamespaceURI, this);



			el.SetLineInfo(reader.LineNumber, reader.LinePosition);
			int attCnt = reader.AttributeCount;
			if(attCnt > 0)
			{
				for (int i = 0; i < attCnt; ++i)
				{
					reader.MoveToAttribute(i);
					LineInfoXmlAttribute att = new LineInfoXmlAttribute(reader.Prefix,reader.LocalName, reader.NamespaceURI, this);
					att.setLineInfo(reader.LineNumber, reader.LinePosition);
					att.Value = reader.Value;
					el.Attributes.Append(att);
				}
				reader.MoveToElement();
			}
			if(!reader.IsEmptyElement)
			{
				while (reader.Read()) 
				{
					switch (reader.NodeType) 
					{
						case XmlNodeType.Element:
							el.AppendChild(loadElement(reader));
							break;
						case XmlNodeType.Text:
							el.AppendChild(CreateTextNode(reader.Value));
							break;
						case XmlNodeType.CDATA:
							el.AppendChild(this.CreateCDataSection(reader.Value));
							break;
						case XmlNodeType.ProcessingInstruction:
							Console.Write("<?{0} {1}?>", reader.Name, reader.Value);
							break;
						case XmlNodeType.EntityReference:
							el.AppendChild(this.CreateEntityReference(reader.Name));
							break;
						case XmlNodeType.EndElement:
							return el;
							break;
						case XmlNodeType.SignificantWhitespace:
                            if (PreserveWhitespace)
							    el.AppendChild(this.CreateSignificantWhitespace(reader.Value));
							break;
						case XmlNodeType.Whitespace:
                            if (PreserveWhitespace)
                                el.AppendChild(this.CreateWhitespace(reader.Value));
							break;
					}       
				}
			}
			return el;
		}


	}

	public class LineInfoXmlElement : XmlElement, IXmlLineInfo 
	{
		int lineNumber = 0;
		int linePosition = 0;

		internal LineInfoXmlElement( string prefix, string localname, string nsURI, XmlDocument doc ) 
			:base( prefix, localname, nsURI, doc ) 
		{
		}   
		public void SetLineInfo( int linenum, int linepos ) 
		{
			lineNumber = linenum;
			linePosition = linepos;
		}
	
		public int LineNumber 
		{
			get 
			{
				return lineNumber;
			}
		}
	
		public int LinePosition 
		{
			get 
			{
				return linePosition;
			}
		}

		public bool HasLineInfo(){return lineNumber > 0;} 
	}

	public class LineInfoXmlAttribute : XmlAttribute, IXmlLineInfo
	{
		protected int m_lineNum = 0;
		protected int m_linePos = 0;

		internal LineInfoXmlAttribute(string prefix, string localName, string namespaceURI, XmlDocument doc)
			:base(prefix==null?"":prefix, localName==null?"":localName, namespaceURI==null?"":namespaceURI, doc)
		{
		}

		internal void setLineInfo(int lineNum, int linePos)
		{
			m_lineNum = lineNum;
			m_linePos = linePos;
		}

		#region IXmlLineInfo Members
		public int LineNumber {get{return m_lineNum;}}
		public int LinePosition {get{return m_linePos;}}
		public bool HasLineInfo() {return m_lineNum > 0;}
		#endregion

	}


}
